package br.com.mmm.javacenter.framework.dao;

import java.io.Serializable;
import java.util.GregorianCalendar;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Example;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;

import br.com.mmm.javacenter.framework.annotations.Dao;
import br.com.mmm.javacenter.framework.entity.EntidadeBase;
import br.com.mmm.javacenter.user.entity.UltimaAlteracao;

@Dao
public class BaseDao<T extends EntidadeBase<T>> implements RepositoryBase<T>{
	protected Session session;
	protected Class<? extends EntidadeBase<?>> klass;
	
	
	
	public BaseDao(){
		this.session = HibernateUtil.getSession();
	}
	
	public void alterar(T entity) {
		entity.setUltimaAlteracao(new UltimaAlteracao(GregorianCalendar.getInstance()));
		entity = (T) session.merge(entity);
		session.update(entity);
	}

	
	public void atualizar(T entity) {
		// entity.setDataUltimaAlteracao(GregorianCalendar.getInstance());
		session.refresh(entity);
		
	}

	
	@SuppressWarnings("unchecked")
	public T consultaPorCodigo(Serializable codigo) {
		return (T) session.load(klass, codigo);
	}
	
	public T consultaPorCodigo(T codigo) {
		return (T) session.load(codigo.getClass(), codigo.getId());
	}
	
	
	@SuppressWarnings("unchecked")
	public List<T> consultaPorExemplo(T entity) {
		Criteria criteria = session.createCriteria(klass);
		if (entity != null){
			Example example = Example.create(entity);
			criteria.add(example);
		}
		return criteria.list();
	}

	
	public void excluir(T entity) {
		// TODO Auto-generated method stub
		
	}

	
	public void incluir(T entity) {
		session.persist(entity);
	}

	
	public void mesclar(T entity) {
		this.session.update(entity);
		
	}

	
	public Integer contar() {
		// TODO Auto-generated method stub
		return null;
	}

	
	@SuppressWarnings("unchecked")
	public List<T> listarTodos() {
		return session.createCriteria(klass).list();
	}
	
	public List<T> listarTodos(Class klass) {
		return session.createCriteria(klass).list();
	}
	public ListPagging<T> listarPagina(Integer pagina) {
		return listarPagina(this.klass,pagina);
	}
	public ListPagging<T> listarPagina(Class klass,Integer pagina) {
		if(pagina==0)pagina=1;
		Criteria criteria = session.createCriteria(klass);
		criteria.setProjection(Projections.count("id"));
		
		long totalReg = (Long) criteria.list().get(0);
		
		Criteria criteria2 = session.createCriteria(klass);
		criteria2.setFirstResult((pagina-1)*10);
		criteria2.setMaxResults(((pagina-1)*10)+10);
		
		return new ListPagging<T>(criteria2.list(),(int) totalReg);
	}

	public Class klass() {
		return klass;
	}
	public void klass(Class<?> klass) {
		this.klass = (Class<? extends EntidadeBase<?>>) klass;
	}

	
	@Override
	public List<T> listarPagina(Integer pagina, Integer displayTagOrder, Integer displayTagSort) {
		if(pagina==0)pagina=1;
		if(displayTagOrder==0)displayTagOrder=1;
		if(displayTagSort==0)displayTagSort=1;
		
		Criteria criteria = session.createCriteria(klass);
		criteria.setProjection(Projections.count("id"));
		
		long totalReg = (Long) criteria.list().get(0);
		
		Criteria criteria2 = session.createCriteria(klass);
		criteria2.setFirstResult((pagina-1)*10);
		criteria2.setMaxResults(((pagina-1)*10)+10);
		if(displayTagOrder==1){
			criteria2.addOrder(Order.asc(EntidadeBase.getCampos(klass).get(displayTagSort-1).getName()));
		}else{
			criteria2.addOrder(Order.desc(EntidadeBase.getCampos(klass).get(displayTagSort-1).getName()));
		}
		return new ListPagging<T>(criteria2.list(),(int) totalReg);
	}


}
